import VNode from '../vdom/vnode.js'
import { vmodel } from './grammer/vmodel.js'
import { vfor } from './grammer/vfor.js'
import { checkvbind } from './grammer/vbind.js'
import { checkvon } from './grammer/von.js'
import { mergeObj } from '../util/ObjectUtil.js'
import { perpareRander, getTemplate2Vnode, getVnode2Template, clearMap } from './render.js'
/**
*不在初始化进行挂载，方便后续进行挂载
*@param {Class} Hue 类Hue
*/
export function initMount(Hue) {
  Hue.prototype.$mount = function (el) {
    let vm = this
    let rootDom = document.getElementById(el)
    mount(vm, rootDom)
  }
}

/**
*把元素进行挂载
*@param {Hue} vm 创建的Hue实例
*@param {dom} elm 挂载的根节点
*/
export function mount(vm, elm) {
  console.log('begin mount')
  vm._vnode = constructVNode(vm, elm, null)
  // 预备渲染
  perpareRander(vm, vm._vnode)
  console.log(getTemplate2Vnode())
  console.log(getVnode2Template())
}

/**
*创建虚拟节点（深度优先搜索）
*@param {Hue} vm 创建的Hue实例
*@param {dom} elm 虚拟节点对应的真实dom
*@param {VNode} parent 当前虚拟节点对应的父节点
*/
function constructVNode(vm, elm, parent) {
  let vnode = constructInstruction(vm, elm, parent)
  if (!vnode) {
    let tag = elm.nodeName
    let children = []
    let text = getNodeText(elm)
    let data = null
    let nodeType = elm.nodeType
    vnode = new VNode(tag, elm, children, parent, text, data, nodeType)
    if (vnode.nodeType === 1 && vnode.elm.getAttribute('env')) {
      vnode.env = mergeObj(vnode.env, JSON.parse(vnode.elm.getAttribute('env')))
    } else {
      vnode.env = mergeObj(vnode.env, parent ? parent.env : {})
    }
  }
  checkvbind(vm, vnode)
  checkvon(vm, vnode)
  let childs = vnode.nodeType === 0 ? vnode.parent.elm.childNodes : elm.childNodes
  //循环长度得提前确定，不然后面v-for添加节点后，长度变长，则虚拟节点的children多添加了
  let len = vnode.nodeType === 0 ? vnode.parent.elm.childNodes.length : elm.childNodes.length
  for (let i = 0; i < len; i++) {
    let child = constructVNode(vm, childs[i], vnode)
    if (child instanceof VNode) {
      // 返回单一节点
      vnode.children.push(child)
    } else {
      // 返回节点数组（v-for）
      vnode.children = vnode.children.concat(child)
    }
  }
  return vnode
}

/**
*获取当前节点的文本内容
*@param {dom} elm 虚拟节点对应的真实dom
*/
function getNodeText(elm) {
  if (elm.nodeType === 3) return elm.nodeValue
  else return ''
}

/**
*创建v-model
*@param {Hue} vm 创建的Hue实例
*@param {dom} elm 虚拟节点对应的真实dom
*@param {VNode} parent 当前虚拟节点对应的父节点
*/
function constructInstruction(vm, elm, parent) {
  if (elm.nodeType === 1) {
    let attributeNames = elm.getAttributeNames()
    if (attributeNames.indexOf('v-model') > -1) {
      vmodel(vm, elm, elm.getAttribute('v-model'))
    }
    if (attributeNames.indexOf('v-for') > -1) {
      return vfor(vm, elm, parent, elm.getAttribute('v-for'))
    }
  }
}

/**
*创建v-model
*@param {Hue} vm 创建的Hue实例
*@param {string} dataName 虚拟节点对应的真实dom
*/
export function rebuild(vm, dataName) {
  let virtualNodes = getTemplate2Vnode().get(dataName)
  for (const virtualNode of virtualNodes) {
    virtualNode.parent.elm.innerHTML = ''
    virtualNode.parent.elm.appendChild(virtualNode.elm)
    let result = constructVNode(vm, virtualNode.elm, virtualNode.parent)
    virtualNode.parent.children = [result]
  }
  clearMap()
  perpareRander(vm, vm._vnode)
}